import loadable from '@loadable/component';
import Loading from '@/components/Loading';

/**
 * 处理路由数据，即动态增加路由 （增加component，补充url）
 * code 格式不同（xxx:xxxx:xxx，xxx/xxxx/xxxx），后续的处理逻辑也需要对应的同步修改
 *
 * @param {*} [routers=[]]
 * routers: {
 *      code: 'xxx/xxx/xxx',    // 根据code映射组件路径 permission/manage -> pages/Permission/Manage/index.jsx
 *      children: [],           // 子路由
 *      icon: '',               // 页面菜单的icon
 *      label: '',              // 页面菜单的名称
 *      layout: '',             // 页面的布局名称
 *      showInMenu: '',         // 是否展示在菜单上
 *      index: boolean,         // TODO，根路径时的跳转路径
 *      rest,                   // 其他数据
 * }
 * @return {*} 一维路由数组
 */
export const addDynamicRoute = (routers=[]) => {
    const pages = import.meta.glob('@/pages/*/index.jsx');
    const reg = new RegExp(BASEDIR);
    const codeSplit = '/';

    return routers.map(item => {
        const {code, children, ...rest} = item;
        const url = (code || '').replace(reg, '').replace(/^\/+/, ''); // url需要以 / 开头
        const params = url.split(codeSplit).filter(Boolean);
        const filePath = params.map(i => i.split('-').map(j => j.charAt(0).toUpperCase() + j.slice(1)).join('')).join('/');
        const path = `/src/pages/${filePath}/index.jsx`;
        const component = pages[path] ? loadable(pages[path], { fallback: <Loading/> }) : <Loading tip="配置与资源不符，请联系管理员处理"/>;

        let child = [];
        if(Array.isArray(children) && children.length) child = addDynamicRoute(children);

        return ({
            component,
            ...rest,
            ...(rest.url ? {} : {url: `${BASEDIR}/${url}`}), // code是不包含BASEDIR，不以/开头的纯url
            children: child,
            code, // 先保留，后面获取菜单数据时可以用来筛选有权限的菜单
        });
    })
};


/*
    路由文件使用的地方
        路由渲染 - 必需要有 path、component
        菜单 - 必需要有 key
        面包屑

    路由结构:
        routers: {
             code: 'xxx:xxx:xxx',    // 权限编码，根据code映射组件路径 permission:manage -> pages/Permission/Manage/index.jsx
             children: [],           // 子路由
             icon: '',               // 页面菜单的icon
             label: '',              // 页面菜单的名称
             layout: '',             // 页面的布局名称
             showInMenu: '',         // 是否展示在菜单上
             index: boolean,         // TODO，根路径时的跳转路径
             rest,                   // 其他数据
        }
*/

/*
    给路由增加 key ，其他数据原样返回
*/
export const mapMenuAddKey = (menus=[], parentKey='') => {
    return (menus || []).map(item => {
        let {children, url} = item;
        const key = `${parentKey}/${url.replace(/^\//, '')}`;
        item.key = key;

        if(Array.isArray(children) && children.length) item.children = mapMenuAddKey(children, key);

        return item;
    });
};

/*
    获取可以展示的菜单数据，既校验showInMenu，也校验是否有权限
    data: 菜单数据
    modules: 权限数据，权限数组
    return: 有权限的菜单数据

    {
        key,    // item 的唯一标志
        icon,   // 菜单图标
        label,  // 菜单标题
        title,  // 收缩时展示的悬浮标题
    }
*/
export const getMenuData = (data=[], modules=[], forRoute=false) => {
    return data.map(item => {
        const { showInMenu=false, url='', code='' } = item;
        item.title = item.label || url || key || '菜单名称';
        // 当前item不用展示在菜单 或 没有权限
        if(!showInMenu && !forRoute) return undefined;

        let child = [];
        if(Array.isArray(item.children) && item.children.length) child = getMenuData(item.children, modules, forRoute);

        const exist = (modules || []).find(i => i.code && (i.code.replace(/^\/+/, '') === code.replace(/^\/+/, '')));

        if(!exist && !child.length) return undefined; // 没有权限，且没有子路由

        item.children = child.slice(0);

        return item;
    }).filter(Boolean);
};


/**
 * 获取渲染菜单需要的数据
 *  其实就是格式化菜单数据
 * @param {*} [data=[]]
 * @return {*} 
 */
export const getMenuRenderData = (data=[]) => {
    return data.map(item => {
        // const { showInMenu=false, url='', children=[], code, index, ...rest } = item;
        const { key, icon, label, title, children=[], ...rest } = item;
        let menuObj = { key, icon, label, title };
        if(Array.isArray(children) && children.length) menuObj.children = getMenuRenderData(children);

        return menuObj;
    }).filter(Boolean);
};


/**
 *打平路由
 *
 * @param {*} [data=[]] 路由tree数据
 * @return {*} 打平后的路由
 */
export const flatRoutes = (data=[]) => {
    let routers = [];
    (data || []).map(item => {
        // 只要有url就先记录路由
        if(item.url) routers.push(item);

        if(Array.isArray(item.children) && item.children.length) routers = routers.concat(flatRoutes(item.children));
    });

    return routers;
};

/*
    获取当前页面的 路由路径
*/
export const getMenuPath = (targetId='', tree=[], objectKey='url') => {
    let stack = tree.map(node => ({ node, path: [node] })); // 初始化堆栈，每个元素包含节点和路径（对象）
    let visited = new Set(); // 用于跟踪已访问过的节点

    while (stack.length > 0) {
        let { node, path } = stack.pop();

        if (node[objectKey] === targetId) {
            return path; // 找到目标节点，返回节点
        }

        if (!visited.has(node[objectKey])) {
            visited.add(node[objectKey]);

            // 将当前节点的所有子节点压入堆栈，并更新路径
            for (let child of node.children || []) {
                stack.push({ node: child, path: [...path, child] });
            }
        }
    }

    return null; // 如果没有找到目标节点，返回null
};